package com.yueyang.sojourn.server.controller.order;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.yueyang.sojourn.server.common.LoginNeedless;
import com.yueyang.sojourn.server.common.consts.Constants;
import com.yueyang.sojourn.server.controller.BaseController;
import com.yueyang.sojourn.server.controller.model.JsonResult;
import com.yueyang.sojourn.server.model.enums.OrderStatusEnum;
import com.yueyang.sojourn.server.model.enums.PayConstants;
import com.yueyang.sojourn.server.model.po.*;
import com.yueyang.sojourn.server.model.vo.SojournOrderDetailVo;
import com.yueyang.sojourn.server.model.vo.SojournOrderListVo;
import com.yueyang.sojourn.server.model.vo.SojournOrderTouristVo;
import com.yueyang.sojourn.server.model.vo.SojournOrderVo;
import com.yueyang.sojourn.server.service.attachdetail.AttachDetailService;
import com.yueyang.sojourn.server.service.sojourn.merch.SojournMerchService;
import com.yueyang.sojourn.server.service.sojourn.order.*;
import com.yueyang.sojourn.server.service.sojourn.project.SojournProjectService;
import com.yueyang.sojourn.server.service.sojourn.transaction.SojournTransactionService;
import com.yueyang.sojourn.server.utils.CardValidUtil;
import com.yueyang.uc.model.UcUserV1;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;

/**
 * 订单后台服务
 * @author andy.yang
 * @version v1
 * @summary
 * @Copyright (c) 2019, yueyang Group All Rights Reserved.
 * @since 2020/3/17
 */
@Api(tags = "订单 API")
@RestController
@RequestMapping("/sojourn/order")
@Slf4j
public class SojournOrderController extends BaseController {
    @Autowired
    SojournProjectService projectService;
    @Autowired
    SojournMerchService merchService;
    @Autowired
    SojournOrderService orderService;
    @Autowired
    SojournOrderMerchService orderMerchService;
    @Autowired
    SojournOrderTouristService orderTouristService;
    @Autowired
    AttachDetailService attachDetailService;
    @Autowired
    SojournOrderMsgService orderMsgService;
    @Autowired
    SojournTransactionService transactionService;
    @Autowired
    SojournOrderRefundService refundService;


    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
    }


    @ApiImplicitParam(name = "X-Token", paramType = "header", required = true)
    @ApiOperation(value = "订单列表分页查询")
    @GetMapping("/page")
    public PageInfo<SojournOrderListVo> findPage(@ApiParam(value = "关键词") @RequestParam(required = false) String keyWord,
                                             @ApiParam(value = "下单时间开始") @RequestParam(required = false) Long createStartTime,
                                             @ApiParam(value = "下单时间结束") @RequestParam(required = false) Long createEndTime,
                                             @ApiParam(value = "订单状态") @RequestParam(required = false) Integer status,
                                             @RequestParam int pageNo,
                                             @RequestParam int pageSize,
                                             HttpServletRequest request) {
        String token = request.getHeader(Constants.LOGIN_TOKEN);
        UcUserV1 loginUserV1 = super.getLoginUser();
        long loginUserId = loginUserV1.getId();
        Date createStartTimeTemp = null;
        Date createEndTimeTemp = null;
        if(createStartTime != null && createStartTime > 0){
            try {
                createStartTimeTemp = new Date(createStartTime);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        if(createEndTime != null && createEndTime > 0){
            try {
                createEndTimeTemp = new Date(createEndTime);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //1: 查询订单
        PageInfo<SojournOrder> orderPageInfo = orderService.findPage(null,keyWord,createStartTimeTemp,createEndTimeTemp,status,null,pageNo,pageSize);
        if(orderPageInfo.getList().isEmpty()){
            PageInfo rs = new PageInfo();
            BeanUtils.copyProperties(orderPageInfo,rs);
            return rs;
        }

        List<Long> orderIds = new ArrayList<>();
        List<Long> projectIds = new ArrayList<>();
        List<Long> picAttachIds = new ArrayList<>();
        orderPageInfo.getList().stream().forEach((order) -> {
            if(!projectIds.contains(order.getMerchProjectId()));{
                projectIds.add(order.getMerchProjectId());
            }
            if(!picAttachIds.contains(order.getMerchPicAttachId()));{
                picAttachIds.add(order.getMerchPicAttachId());
            }

            orderIds.add(order.getId());
        });

        //2: 拼装异步
        //查询项目
        FutureTask<List<SojournProject>> projectListTask = null;
        if(!projectIds.isEmpty()) {
            Callable<List<SojournProject>> projectListCallable = () -> projectService.findByIds(projectIds);
            projectListTask = new FutureTask<>(projectListCallable);
        }

        //查询图片
        FutureTask<List<AttachDetail>> attachListTask = null;
        if(!picAttachIds.isEmpty()) {
            Callable<List<AttachDetail>> attachListCallable = () -> attachDetailService.selectListByIds(picAttachIds);
            attachListTask = new FutureTask<>(attachListCallable);
        }

        //3：异步执行查询
        if(projectListTask != null){
            executorService.submit(projectListTask);
        }
        if(attachListTask != null) {
            executorService.submit(attachListTask);
        }

        //4：获取数据
        Map<Long,SojournProject> projectMap = new HashMap();
        Map<Long,AttachDetail> attachDetailMap = new HashMap();
        try {
            List<SojournProject> projects = projectListTask == null ? new ArrayList<>() : projectListTask.get();
            projects.stream().forEach((project) ->{projectMap.put(project.getId(),project);});

            List<AttachDetail> attachDetails = attachListTask == null ? new ArrayList<>() : attachListTask.get();
            attachDetails.stream().forEach((detail) ->{attachDetailMap.put(detail.getId(),detail);});
        } catch (Exception e) {
            e.printStackTrace();
        }

        //5：拼装数据
        PageInfo<SojournOrderListVo> pageInfo = new PageInfo();
        BeanUtils.copyProperties(orderPageInfo,pageInfo);
        pageInfo.setList(new ArrayList());
        orderPageInfo.getList().stream().forEach((order) ->{
            SojournOrderListVo orderListVo = new SojournOrderListVo();
            BeanUtils.copyProperties(order,orderListVo);
            //手机号脱敏
            if(CardValidUtil.validMobile(orderListVo.getCreatorPhone())){
                orderListVo.setCreatorPhone(orderListVo.getCreatorPhone().substring(0, 3) + "****" + orderListVo.getCreatorPhone().substring(7, 11));
            }
            //优惠
            orderListVo.setMerchSales(JSON.parseArray(order.getMerchSale(), Integer.class));
            //实际付款:应该是交易单中的数据，但目前为止与订单最价是一样的，暂时使用订单总价，没必要浪费性能 todo
            if(OrderStatusEnum.TO_BE_TRIP.getCode() == order.getStatus()
                    || OrderStatusEnum.DEALED.getCode() == order.getStatus()
                    || OrderStatusEnum.REFUNDED.getCode() == order.getStatus()) {
                orderListVo.setTransPrice(order.getTotalPrice());
            }else {
                orderListVo.setTransPrice(new BigDecimal(0));
            }
            //项目
            if(order.getMerchProjectId() != null && projectMap.get(order.getMerchProjectId()) != null) {
                orderListVo.setMerchProjectName(projectMap.get(order.getMerchProjectId()).getName());
            }
            //图片
            if(order.getMerchPicAttachId() != null && attachDetailMap.get(order.getMerchPicAttachId()) != null){
                AttachDetail detail = attachDetailMap.get(order.getMerchPicAttachId());
                AttachDetail temp = null;
                if(detail != null){
                    temp = new AttachDetail();
                    BeanUtils.copyProperties(detail,temp);
                }
                orderListVo.setPicAttachDetail(temp);
            }
            pageInfo.getList().add(orderListVo);
        });

        return pageInfo;
    }

    @ApiImplicitParam(name = "X-Token", paramType = "header", required = true)
    @ApiOperation(value = "订单详情查询")
    @GetMapping("/{orderId}")
    public SojournOrderDetailVo findById(@ApiParam(value = "订单id") @PathVariable Long orderId, HttpServletResponse response){
        SojournOrder order = orderService.findById(orderId);
        if(order == null){
//            response.setStatus(HttpStatus.SC_NOT_FOUND);
            return null;
        }

        SojournOrderDetailVo detailVo = new SojournOrderDetailVo();
        BeanUtils.copyProperties(order,detailVo);
        //手机号脱敏
        if(CardValidUtil.validMobile(detailVo.getCreatorPhone())){
            detailVo.setCreatorPhone(detailVo.getCreatorPhone().substring(0, 3) + "****" + detailVo.getCreatorPhone().substring(7, 11));
        }
        if(order.getMerchPicAttachId() != null && order.getMerchPicAttachId() >= 0) {
            try {
                AttachDetail attachDetail = attachDetailService.selectByPrimaryKey(order.getMerchPicAttachId());
                detailVo.setPicAttachDetail(attachDetail);
            }catch (Exception e){
                log.error(e.getMessage(),e);
            }
        }
        //交易信息
        if(OrderStatusEnum.DEALED.getCode() == order.getStatus()
                || OrderStatusEnum.TO_BE_TRIP.getCode() == order.getStatus()
                || OrderStatusEnum.REFUNDED.getCode() == order.getStatus()){
            SojournTransaction transaction = transactionService.findPayByOrderSn(order.getSn());
            if(transaction != null){
                detailVo.setThirdTransId(transaction.getThirdTransId());
                detailVo.setChannelType(transaction.getChannelType());

                //已成交、已付款、已退款：显示实付款
                if(OrderStatusEnum.TO_BE_TRIP.getCode() == order.getStatus()
                    || OrderStatusEnum.DEALED.getCode() == order.getStatus()
                        || OrderStatusEnum.REFUNDED.getCode() == order.getStatus()){
                    detailVo.setTransPrice(new BigDecimal(transaction.getTotalFee()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                }
            }
        }
        //退款信息
        if(OrderStatusEnum.REFUNDED.getCode() == order.getStatus()){
            SojournOrderRefund refund = refundService.findByOrderId(orderId);
            if(refund != null){
                detailVo.setRefundReason(refund.getReason());
            }
        }
        //游客信息
        List<SojournOrderTourist> tourists = orderTouristService.findByOrderId(orderId);
        List<SojournOrderTouristVo> orderTouristVos = new ArrayList<>();
        tourists.stream().forEach((orderTourist)->{
            SojournOrderTouristVo vo = new SojournOrderTouristVo();
            BeanUtils.copyProperties(orderTourist,vo);
            orderTouristVos.add(vo);
        });
        detailVo.setOrderTourists(orderTouristVos);
        //商品
        SojournMerch merch = merchService.selectByPrimaryKey(order.getMerchId());
        detailVo.setMerchDesc(merch.getDesc());
        return detailVo;
    }


    /**
     * 发送核销订单验证码
     *
     * @param
     * @return
     */
    @ApiImplicitParam(name = "X-Token", paramType = "header", required = true)
    @ApiOperation(value = "发送核销订单验证码")
    @PostMapping("/{orderId}/clinch/captcha")
    public String sendClinchOrderCaptcha(@ApiParam(value = "订单id") @PathVariable Long orderId) {
        UcUserV1 loginUser = getLoginUser();
        orderMsgService.sendDealCaptcha(loginUser.getPhone(),orderId);
        return loginUser.getPhoneShow() == null ?
                loginUser.getPhone().substring(0,3) + "****" + loginUser.getPhone().substring(7) : loginUser.getPhoneShow();
    }

    /**
     *核销订单
     *
     * @param orderId
     * @return
     */
    @ApiOperation(value = "核销订单")
    @ApiImplicitParam(name = "X-Token", paramType = "header", required = true)
    @PostMapping("/{orderId}/clinch")
    public JsonResult<SojournOrderVo> clinchOrder(@ApiParam(value = "订单id") @PathVariable Long orderId,
                                                  @ApiParam(value = "短信验证码") @RequestParam("captcha") String captcha) {
        SojournOrder order = orderService.findById(orderId);
        if(order == null){
            return fail("订单不存在");
        }
        if(OrderStatusEnum.TO_BE_TRIP.getCode() != order.getStatus()){
            return fail("订单状态错误，无法核销");
        }
        if(!orderMsgService.verifiDealCaptcha(getLoginUser().getPhone(),orderId,captcha)){
            return fail("验证码输入错误");
        }
        orderService.updateDealed(orderId,getLoginUserId());
        return ok();
    }
}
